#include "../include/cqueue.h"

d_link_node_t *d_link_node_create(void *ptr){
    d_link_node_t *node=(d_link_node_t*)calloc(1,sizeof(d_link_node_t));
    node->ptr=ptr;
    return node;
}

void d_link_node_splice_self(d_link_node_t *node){
    if(node->prev){
        node->prev->next=node->next;
    }
    if(node->next){
        node->next->prev=node->prev;
    }
    node->prev=node->next=NULL;
}

void d_link_node_destory(d_link_node_t *node){
    d_link_node_splice_self(node);
    free(node);
}

void d_link_node_move_front_of(d_link_node_t *target,d_link_node_t *node){
    d_link_node_splice_self(node);
    if(target->prev){
        node->prev=target->prev;
        node->prev->next=node;
    }
    node->next=target;
    target->prev=node;
}


d_list_t *d_list_create(){
    d_list_t *d_list=(d_list_t*)calloc(1,sizeof(d_list_t));
    d_list->dummy_head=d_link_node_create(NULL);
    d_list->dummy_tail=d_link_node_create(NULL);
    d_list->dummy_head->next=d_list->dummy_tail;
    d_list->dummy_tail->prev=d_list->dummy_head;
    return d_list;
}

void d_list_destory(d_list_t *d_list){
    for(d_link_node_t *node=d_list->dummy_head;node;){
        d_link_node_t *tmp=node;
        node=node->next;
        d_link_node_destory(tmp);
    }
    free(d_list);
}

void d_list_push_back(d_list_t *d_list,d_link_node_t *node){
    d_link_node_move_front_of(d_list->dummy_tail,node);
}


cqueue_t *cqueue_create(size_t size){
    cqueue_t *cqueue=(cqueue_t*)malloc(sizeof(cqueue_t));
    cqueue->d_list_arr=(d_list_t **)calloc(size,sizeof(d_list_t*));
    for(size_t i=0;i<size;i++){
        cqueue->d_list_arr[i]=d_list_create();
    }
    cqueue->front=0;
    cqueue->size=size;
    return cqueue;
}

void cqueue_destory(cqueue_t *cqueue){
    for(size_t i=0;i<cqueue->size;i++){
        d_list_destory(cqueue->d_list_arr[i]);
    }
    free(cqueue);
}

void cqueue_step_next(cqueue_t *cqueue){
    cqueue->front = (cqueue->front+1)%cqueue->size;
}

d_list_t *cqueue_front(cqueue_t *cqueue){
    return cqueue->d_list_arr[cqueue->front];
}

void cqueue_move_to_rear(cqueue_t *cqueue,d_link_node_t *node){
    size_t tail_idx=(cqueue->front+cqueue->size-1)%cqueue->size;
    d_list_push_back(cqueue->d_list_arr[tail_idx],node);
}

void cqueue_move_to_front(cqueue_t *cqueue,d_link_node_t *node){
    size_t front_idx=(cqueue->front+1)%cqueue->size;
    d_list_push_back(cqueue->d_list_arr[front_idx],node);
}
